package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.commons.constants.CourseConstants;
import com.xuecheng.commons.enums.ErrorCode;
import com.xuecheng.commons.model.dto.BindTeachplanMediaDto;
import com.xuecheng.commons.model.dto.BindTeachplanWorkDto;
import com.xuecheng.commons.model.dto.TeachplanDto;
import com.xuecheng.commons.model.vo.MediaVo;
import com.xuecheng.commons.model.vo.ResponseResult;
import com.xuecheng.commons.model.vo.TeachplanVo;
import com.xuecheng.commons.model.vo.WorkVo;
import com.xuecheng.commons.utils.BeanHelper;
import com.xuecheng.content.domain.CourseBase;
import com.xuecheng.content.domain.Teachplan;
import com.xuecheng.content.domain.TeachplanMedia;
import com.xuecheng.content.domain.TeachplanWork;
import com.xuecheng.content.mappers.TeachplanMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.TeachplanMediaService;
import com.xuecheng.content.service.TeachplanService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.content.service.TeachplanWorkService;
import com.xuecheng.media.api.MediaClient;
import com.xuecheng.teaching.api.TeachingClient;
import com.xuecheng.web.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程计划 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-07-16
 */
@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan> implements TeachplanService {
        @Autowired
        private TeachplanMapper teachplanMapper;
        @Autowired
        private CourseBaseService courseBaseService;
        @Autowired
        private MediaClient mediaClient;
        @Autowired
        private TeachplanMediaService teachplanMediaService;

        @Override
        public ResponseResult treeNodes(Long courseId) {
                // 查询所有课程大纲
                List<TeachplanVo> treeplanVos =  teachplanMapper.treeNodes(courseId);
                // 遍历 提取一级大纲
                TeachplanVo tree = treeplanVos.stream().filter(teachplanVo -> teachplanVo.getGrade() == 1)
                        .findFirst().get();
                // 遍历提取二级大纲
                List<TeachplanVo> treeTwos = treeplanVos.stream().filter(teachplanVo -> teachplanVo.getGrade() == 2)
                        .collect(Collectors.toList());
                // 将二级大纲设置到 一级大纲中
                tree.setTeachPlanTreeNodes(treeTwos);
                // 获取课程对象
                CourseBase courseBase = courseBaseService.getById(courseId);
                Integer planNum = 0;
                // 遍历二级大纲获取 三级大纲 注意大纲id匹配
                for (TeachplanVo treeTwo : treeTwos) {
                        List<TeachplanVo> threes = treeplanVos.stream().filter(teachplanVo -> teachplanVo.getGrade() == 3
                                        && teachplanVo.getParentid().equals(treeTwo.getId()))
                                .collect(Collectors.toList());
                        treeTwo.setTeachPlanTreeNodes(threes);
                        planNum += threes.size();
                }
                courseBase.setPlanNum(planNum);
                courseBaseService.updateById(courseBase);
                return ResponseResult.okResult(tree);
        }

        @Override
        @Transactional
        public ResponseResult saveOrUpdate(TeachplanDto teachplanDto) {
                //判断课程
                Long courseId = teachplanDto.getCourseId();
                CourseBase courseBase = courseBaseService.getById(courseId);
                // 判断课程审核状态
                if(! courseBase.getAuditStatus().equals(CourseConstants.AUDIT_DISPAST_STATUS)
                        && ! courseBase.getAuditStatus().equals(CourseConstants.AUDIT_UNPAST_STATUS)) {
                        throw new BusinessException(ErrorCode.UPDATEEERROR);
                }
                // 判断parentId 为空，设置初始化id
                if(teachplanDto.getParentid() == null){
                        LambdaQueryWrapper<Teachplan> qw = new LambdaQueryWrapper<>();
                        qw.eq(Teachplan::getGrade,CourseConstants.FIRST_LEVEL);
                        qw.eq(Teachplan::getCourseId,teachplanDto.getCourseId());
                        Teachplan teachplan = this.getOne(qw);
                        teachplanDto.setParentid(teachplan.getParentid());
                }
                // dto 转为实体类
                Teachplan teachplan = BeanHelper.copyProperties(teachplanDto, Teachplan.class);
                // 判断是 新增 还是 修改
                Boolean flag = false;
                if(teachplan.getId() == null){
                        // 如果是三级节点 节点数量+1
                        if(teachplan.getGrade() == 3){
                                courseBase.setPlanNum(courseBase.getPlanNum()+1);
                                courseBaseService.updateById(courseBase);
                        }
                        flag = this.save(teachplan);
                }else {
                        flag = this.updateById(teachplan);
                }
                if(!flag){
                        throw new BusinessException(ErrorCode.ERROR);
                }
                return ResponseResult.okResult();
        }

        @Override
        public ResponseResult deleteById(Long id) {
                Teachplan teachplan = this.getById(id);
                CourseBase courseBase = courseBaseService.getById(teachplan.getCourseId());
                // 判断课程审核状态
                if(! courseBase.getAuditStatus().equals(CourseConstants.AUDIT_DISPAST_STATUS)
                        && ! courseBase.getAuditStatus().equals(CourseConstants.AUDIT_UNPAST_STATUS)) {
                        throw new BusinessException(ErrorCode.UPDATEEERROR);
                }
                if(teachplan.getGrade() == 3){
                        courseBase.setPlanNum(courseBase.getPlanNum()-1);
                        courseBaseService.updateById(courseBase);
                }
                boolean remove = this.removeById(id);
                if(!remove){
                        throw new BusinessException(ErrorCode.DELETEERROR);
                }
                return ResponseResult.okResult(null);
        }

        @Override
        public ResponseResult associateMedia(BindTeachplanMediaDto dto) {
                // 判断基本参数
                if (dto.getTeachplanId() == null || dto.getMediaId() == null) {
                        throw  new BusinessException(ErrorCode.PARAMSERROR);
                }
                // 判断课程状态
                Teachplan teachplan = this.getById(dto.getTeachplanId());
                Long courseId = teachplan.getCourseId();
                CourseBase course = courseBaseService.getById(courseId);
                // 判断审核状态
                String auditStatus = course.getAuditStatus();
                if(!CourseConstants.AUDIT_DISPAST_STATUS.equals(auditStatus) &&
                        ! CourseConstants.AUDIT_UNPAST_STATUS.equals(auditStatus) ) {
                        throw new BusinessException(ErrorCode.MEDIABINDERROR);
                }
                // 远程调用 feign 提供根据媒资id，查询媒资对象
                ResponseResult<MediaVo> result = mediaClient.findById(dto.getMediaId());
                MediaVo vo = result.getData();
                // 查询媒咨绑定数据
                LambdaQueryWrapper<TeachplanMedia> qw = new LambdaQueryWrapper<>();
                qw.eq(TeachplanMedia::getTeachplanId,dto.getTeachplanId());
                TeachplanMedia teachplanMedia = teachplanMediaService.getOne(qw);
                if(teachplanMedia == null) {
                        //4.1 不存在，保存数据
                        teachplanMedia = new TeachplanMedia();
                        teachplanMedia.setMediaId(vo.getId());
                        teachplanMedia.setMediaFilename(vo.getFilename());
                        teachplanMedia.setTeachplanId(dto.getTeachplanId());
                        teachplanMedia.setCourseId(courseId);
                        teachplanMedia.setCreateDate(new Date());
                        teachplanMediaService.save(teachplanMedia);
                }else {
                        //4.2 存在，更新数据
                        teachplanMedia.setMediaId(vo.getId());
                        teachplanMedia.setMediaFilename(vo.getFilename());
                        teachplanMediaService.updateById(teachplanMedia);
                }

                return ResponseResult.okResult();
        }

        @Autowired
        private TeachingClient teachingClient;
        @Autowired
        private TeachplanWorkService teachplanWorkService;

        @Override
        public ResponseResult associateWork(BindTeachplanWorkDto dto) {
                // 判断基本参数
                if(dto.getTeachplanId() == null || dto.getWorkId() == null ){
                        throw new BusinessException(ErrorCode.PARAMSERROR);
                }
                // 判断课程状态
                Teachplan teachplan = this.getById(dto.getTeachplanId());
                Long courseId = teachplan.getCourseId();
                CourseBase course = courseBaseService.getById(courseId);
                // 判断审核状态
                String auditStatus = course.getAuditStatus();
                if(!CourseConstants.AUDIT_DISPAST_STATUS.equals(auditStatus) &&
                        ! CourseConstants.AUDIT_UNPAST_STATUS.equals(auditStatus) ) {
                        throw new BusinessException(ErrorCode.MEDIABINDERROR);
                }
                // 远程调用 feign 提供根据作业id，查询作业对象
                ResponseResult<WorkVo> result = teachingClient.findById(dto.getWorkId());
                WorkVo workVo = result.getData();
                // 查询作业绑定数据
                LambdaQueryWrapper<TeachplanWork> qw = new LambdaQueryWrapper<>();
                qw.eq(TeachplanWork::getTeachplanId,dto.getTeachplanId());
                TeachplanWork one = teachplanWorkService.getOne(qw);
                boolean flag = false;
                if(one == null){
                        TeachplanWork teachplanWork = new TeachplanWork();
                        teachplanWork.setWorkId(dto.getWorkId());
                        teachplanWork.setCreateDate(new Date());
                        teachplanWork.setTeachplanId(dto.getTeachplanId());
                        teachplanWork.setCourseId(courseId);
                        teachplanWork.setWorkTitle(dto.getWorkTitle());

                        flag = teachplanWorkService.save(teachplanWork);
                }else {
                        one.setWorkId(dto.getWorkId());
                        one.setWorkTitle(dto.getWorkTitle());
                        flag = teachplanWorkService.updateById(one);
                }
                if(!flag){
                        throw new BusinessException(ErrorCode.ERROR);
                }
                return ResponseResult.okResult();
        }

        @Override
        public ResponseResult unbind(Long teachplanWorkId, Long courseBaseId) {
                LambdaQueryWrapper<TeachplanWork> qw = new LambdaQueryWrapper<>();
                qw.eq(TeachplanWork::getId,teachplanWorkId);
                qw.eq(TeachplanWork::getCourseId,courseBaseId);
                TeachplanWork work = teachplanWorkService.getOne(qw);
                if(work == null){
                        throw new BusinessException(ErrorCode.NOTFOUND);
                }else {
                        return ResponseResult.okResult(teachplanWorkService.removeById(work));
                }
        }
}
